package client;

import javax.swing.*;
import javax.swing.plaf.metal.MetalBorders;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.regex.Pattern;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;

/**
 * 
 * @author Chris Fraser, Jean-luc Richard
 *
 */

public class SchwimmenClient extends JFrame implements ActionListener
{
	
	private Socket socket;
	
	public static final int DEFAULT_PORT = 4001;
	
	public static final Color PLAYER_COLOR = new Color(81, 168, 255);
	
	private JLabel otherCard1 = new JLabel(createImageIcon("back.jpg"));
	private JLabel otherCard2 = new JLabel(createImageIcon("back.jpg"));
	private JLabel otherCard3 = new JLabel(createImageIcon("back.jpg"));
	private JLabel boardCard1 = new JLabel(createImageIcon("back.jpg"));
	private JLabel boardCard2 = new JLabel(createImageIcon("back.jpg"));
	private JLabel boardCard3 = new JLabel(createImageIcon("back.jpg"));
	private JLabel playerCard1 = new JLabel(createImageIcon("back.jpg"));
	private JLabel playerCard2 = new JLabel(createImageIcon("back.jpg"));
	private JLabel playerCard3 = new JLabel(createImageIcon("back.jpg"));
	private JButton feuer = new JButton("Feuer");
	private JButton schnauz = new JButton("Schnauz");
	private JButton exchange = new JButton("Exchange");
	private JButton close = new JButton("Close");
	private JButton pass = new JButton("Pass");
	private JRadioButton rb1 = new JRadioButton();
	private JRadioButton rb2 = new JRadioButton();
	private JRadioButton rb3 = new JRadioButton();
	private JTextArea status = new JTextArea();
	
	private JButton newUser;
	private JButton regUser;
	private JButton newUserLogin;
	private JButton regUserLogin;
	private JPanel left;
	private JPanel leftNew;
	private JPanel leftReg;
	
	public static final String CARD_CAPTURE = "([A-Z0-10]\\w)";
	
	private Pattern startGame = Pattern.compile("([0-9])" + "," + CARD_CAPTURE + "," + CARD_CAPTURE + "," + CARD_CAPTURE);
	
	private Pattern board = Pattern.compile(CARD_CAPTURE + "," + CARD_CAPTURE + "," + CARD_CAPTURE);
	
	private Pattern exchangeCard = Pattern.compile(CARD_CAPTURE + "," + CARD_CAPTURE);
	
	
	private int playerNum;
	
	public SchwimmenClient()
	{
		this.getContentPane().setBackground(Color.WHITE);
		this.getContentPane().setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
		this.addComponents(this.getContentPane());
		this.setSize(800,600);		
		
		//This is from SchwimmenLogin
		JFrame loginMenu = new SchwimmenLogin();
	}

	/**
	 * The method reads from sockets, checks the incoming message by
	 * calling the checkProtocol method.
	 */
	private void readSocket() throws IOException
	{
	
		String userInput;
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		while ((userInput = br.readLine()) != null)
		{
			this.updateCards(userInput);
			Logger.info("Protocol message from server: " + userInput);
			
		}		
	}
	
	/**
	 * This method is used to send out data to the client through the protocol.
	 */
	public void writeToSocket(String protIn)
	{
		try 
		{
			PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
			out.println(protIn);
			Logger.info("Writing out: " + protIn);
		} 
		catch (IOException e) 
		{
			Logger.error("Unable to write out to socket.");
			System.exit(0);
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) 
	{
		if(e.getSource() == rb1)
		{
			rb2.setSelected(false);
			rb3.setSelected(false);
		}
		if(e.getSource() == rb2)
		{
			rb1.setSelected(false);
			rb3.setSelected(false);
		}
		if(e.getSource() == rb3)
		{
			rb2.setSelected(false);
			rb1.setSelected(false);
		}
		//This is from SchwimmenLogin
		if(e.getSource() == this.newUser)
		{
			//change to other screen
			left.setVisible(false);
			leftNew.setVisible(true);
		}
		if(e.getSource() == this.regUser)
		{
			//change to other screen
			left.setVisible(false);
			leftReg.setVisible(true);
		}
		if(e.getSource() == newUserLogin)
		{
			//Verify then login
			
		}
		if(e.getSource() == regUserLogin)
		{
			//Verify username/password
		}
	}
	
	public void update(String protIn)
	{
		//Check for a new player
		if(startGame.matcher(protIn).matches())
		{
			this.playerNum = Integer.valueOf(protIn.split(",")[0]);
			this.updateCards(protIn.substring(0,2));
		}
		
		else if(board.matcher(protIn).matches())
		{
			this.updateCards(protIn);
		}
	}
	
	public void displayOtherHand(String cards)
	{
		String card1 = cards.split(", ")[0];
		String card2 = cards.split(", ")[1];
		String card3 = cards.split(", ")[2];
		this.otherCard1 = new JLabel(createImageIcon(getFile(card1)));
		this.otherCard2 = new JLabel(createImageIcon(getFile(card2)));
		this.otherCard3 = new JLabel(createImageIcon(getFile(card3)));
	}
	
	public static String getFile(String card)
	{
		return card + ".png";
	}
	
	public void updateCards(String cards)
	{
		String card1 = cards.split(", ")[0];
		String card2 = cards.split(", ")[1];
		String card3 = cards.split(", ")[2];
		this.boardCard1 = new JLabel(createImageIcon(getFile(card1)));
		this.boardCard2 = new JLabel(createImageIcon(getFile(card2)));
		this.boardCard3 = new JLabel(createImageIcon(getFile(card3)));
	}
	
	public void displayScore(String message)
	{
		
	}
	
	public void gameOver(String end)
	{
		if (end.split(",")[1].equals("loss"))
		{
			this.status.setText("Game Over!");
		}
		
		else
		{
			this.status.setText("Congratulations you win!");
		}
	}
	
	public void addComponents(Container c)
	{
		JLabel bg = new JLabel(createImageIcon("cardtable.jpg"));
		JLabel title = new JLabel(createImageIcon("title.jpg"));
		
		JPanel otherCards = new JPanel();
		otherCards.add(this.otherCard1);
		otherCards.add(this.otherCard2);
		otherCards.add(this.otherCard3);
		otherCards.setBackground(Color.WHITE);
		
		JPanel board = new JPanel();
		board.add(this.boardCard1);
		board.add(this.boardCard2);
		board.add(this.boardCard3);
		board.setBackground(Color.WHITE);
		
		JPanel playerCards = new JPanel();
		playerCards.add(this.playerCard1);
		playerCards.add(this.playerCard2);
		playerCards.add(this.playerCard3);
		playerCards.setBackground(PLAYER_COLOR);
		
		//Buttons
		JPanel buttons = new JPanel();
		buttons.add(this.feuer);
		buttons.add(this.schnauz);
		buttons.add(this.exchange);
		buttons.add(this.close);
		buttons.add(this.pass);
		buttons.setBackground(PLAYER_COLOR);
		
		//Card buttons
		JPanel rb = new JPanel();
		
		this.rb1.setBackground(PLAYER_COLOR);
		this.rb2.setBackground(PLAYER_COLOR);
		this.rb3.setBackground(PLAYER_COLOR);
		rb.add(this.rb1);
		rb.add(Box.createRigidArea(new Dimension(35,0)));
		rb.add(this.rb2);
		rb.add(Box.createRigidArea(new Dimension(35,0)));
		rb.add(this.rb3);
		rb.setBackground(PLAYER_COLOR);
		
		title.setAlignmentX(Component.CENTER_ALIGNMENT);
		bg.setAlignmentX(Component.CENTER_ALIGNMENT);
		c.add(title);
		c.add(otherCards);
		c.add(board);
		c.add(playerCards);
		//c.add(bg);
		c.add(rb);
		c.add(buttons);
		c.add(status); //status bar at bottom
	}
	
	//This is from SchwimmenLogin
	public void addLoginComponents(Container c)
	{
		JPanel login = new JPanel();
		login.setLayout(new CardLayout());
		
		//Initial login screen
		left = new JPanel();
		left.setBackground(Color.WHITE);
		left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS));
		newUser = new JButton("New User");
		newUser.setAlignmentX(Component.CENTER_ALIGNMENT);
		newUser.addActionListener(this);
		regUser = new JButton("Registered User");
		regUser.setAlignmentX(Component.CENTER_ALIGNMENT);
		regUser.addActionListener(this);

		left.add(newUser);
		left.add(Box.createRigidArea(new Dimension(0,20)));
		left.add(Box.createRigidArea(new Dimension(0,20)));
		left.add(regUser);
		
		JPanel right = new JPanel();
		right.setBackground(Color.WHITE);
		right.setLayout(new BoxLayout(right, BoxLayout.Y_AXIS));
		JLabel topthree = new JLabel("Top 3 Players");
		topthree.setAlignmentX(Component.CENTER_ALIGNMENT);
		JTextArea ta = new JTextArea();
		ta.setMinimumSize(new Dimension(200, 100));
		ta.setEditable(false);
		ta.setBorder(MetalBorders.getTextFieldBorder());
		right.add(topthree);
		right.add(ta);
		
		newUserLogin = new JButton("Login");
		newUserLogin.setAlignmentX(Component.CENTER_ALIGNMENT);
		newUserLogin.addActionListener(this);
		regUserLogin = new JButton("Login");
		regUserLogin.setAlignmentX(Component.CENTER_ALIGNMENT);
		regUserLogin.addActionListener(this);
		
		//New user section
		leftNew = new JPanel();
		leftNew.setBackground(Color.WHITE);
		leftNew.setLayout(new BoxLayout(leftNew, BoxLayout.Y_AXIS));
		JLabel newUserMsg = new JLabel("Enter your new username:");
		newUserMsg.setAlignmentX(Component.CENTER_ALIGNMENT);
		JTextField newUsername = new JTextField();
		newUsername.setMaximumSize(new Dimension(200, 25));
		JLabel newPass = new JLabel("Enter your new password:");
		newPass.setAlignmentX(Component.CENTER_ALIGNMENT);
		JTextField newUserPass = new JTextField();
		newUserPass.setMaximumSize(new Dimension(200, 25));
		JLabel error = new JLabel("");
		
		leftNew.add(newUserMsg);
		leftNew.add(newUsername);
		leftNew.add(newPass);
		leftNew.add(newUserPass);
		leftNew.add(error);
		leftNew.add(newUserLogin);
		
		
		//Reg user section
		leftReg = new JPanel();
		leftReg.setBackground(Color.WHITE);
		leftReg.setLayout(new BoxLayout(leftReg, BoxLayout.Y_AXIS));
		JLabel regUserMsg = new JLabel("Enter your username:");
		regUserMsg.setAlignmentX(Component.CENTER_ALIGNMENT);
		JTextField regUsername = new JTextField();
		regUsername.setMaximumSize(new Dimension(200, 25));
		JLabel regPass = new JLabel("Enter your password:");
		regPass.setAlignmentX(Component.CENTER_ALIGNMENT);
		JTextField regUserPass = new JTextField();
		regUserPass.setMaximumSize(new Dimension(200, 25));
		
		leftReg.add(regUserMsg);
		leftReg.add(regUsername);
		leftReg.add(regPass);
		leftReg.add(regUserPass);
		leftReg.add(error);
		leftReg.add(regUserLogin);
		
		login.add(left, "Login");
		login.add(leftNew, "New User Login");
		login.add(leftReg, "Reg User Login");
		c.add(login);
		c.add(Box.createRigidArea(new Dimension(20,0)));
		c.add(right);
	}
	
	 protected static ImageIcon createImageIcon(String path)
	 {
		 java.net.URL imgURL = SchwimmenClient.class.getResource(path);
		 if (imgURL != null) 
		 {
			 return new ImageIcon(imgURL);
		 } 
		 else 
		 {
			System.err.println("Couldn't find file: " + path);
			return null;
		 }
	 }
	
	public static void main(String args[])
	{
		SchwimmenLogin sl = new SchwimmenLogin();
		SchwimmenClient sc = new SchwimmenClient();

		String stringPort = args[1];
		
		InetAddress ip = null;
		int port = DEFAULT_PORT;
		
		if (args[0].isEmpty())
		{
			try 
			{
				Logger.error("Assuming local host as IP.");
				ip = InetAddress.getLocalHost();
			} 
			catch (UnknownHostException e) 
			{
				Logger.error("Unable to determine IP.");
			}
		}
		
		else 
		{
			try 
			{
				ip = InetAddress.getByName(args[0]);
			} 
			catch (UnknownHostException e) 
			{
				Logger.error("Unable determine the provided IP.");
			}
		}
		
		if (!stringPort.isEmpty() && stringPort != null)
		{
			port = Integer.valueOf(stringPort);
		}
		
		try 
		{
			sc.socket = new Socket(ip, port);
		} 
		catch (IOException e) 
		{
			Logger.error("Unable to bind socket");
			System.exit(255);
		}
		
		sc.setVisible(true);
	}

}